1. Remove blkif->status field as it's really not needed.
2. Simplify connection logic.
3. Get rid of atomic_t io_pending. There's no need for
atomic r-m-w updates to the work-to-do flag, so replace
with an integer and add barriers where serialisation is
required.
Signed-off-by: Keir Fraser <keir@xensource.com>
while (!kthread_should_stop()) {
wait_event_interruptible(
blkif->wq,
- atomic_read(&blkif->io_pending) ||
- kthread_should_stop());
+ blkif->waiting_reqs || kthread_should_stop());
wait_event_interruptible(
pending_free_wq,
- !list_empty(&pending_free) ||
- kthread_should_stop());
+ !list_empty(&pending_free) || kthread_should_stop());
+
+ blkif->waiting_reqs = 0;
+ smp_mb(); /* clear flag *before* checking for work */
- atomic_set(&blkif->io_pending, 0);
if (do_block_io_op(blkif))
- atomic_inc(&blkif->io_pending);
+ blkif->waiting_reqs = 1;
unplug_queue(blkif);
if (log_stats && time_after(jiffies, blkif->st_print))
* NOTIFICATION FROM GUEST OS.
*/
-irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+void blkif_notify_work(blkif_t *blkif)
{
- blkif_t *blkif = dev_id;
-
- atomic_inc(&blkif->io_pending);
+ blkif->waiting_reqs = 1;
wake_up(&blkif->wq);
+}
+
+irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+ blkif_notify_work(dev_id);
return IRQ_HANDLED;
}
}
spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
- if (more_to_do) {
- atomic_inc(&blkif->io_pending);
- wake_up(&blkif->wq);
- }
+ if (more_to_do)
+ blkif_notify_work(blkif);
if (notify)
notify_remote_via_irq(blkif->irq);
}
/* Back pointer to the backend_info. */
struct backend_info *be;
/* Private fields. */
- enum { DISCONNECTED, CONNECTED } status;
#ifdef CONFIG_XEN_BLKDEV_TAP_BE
/* Is this a blktap frontend */
unsigned int is_blktap;
wait_queue_head_t wq;
struct task_struct *xenblkd;
- atomic_t io_pending;
+ unsigned int waiting_reqs;
request_queue_t *plug;
/* statistics */
void blkif_xenbus_init(void);
+void blkif_notify_work(blkif_t *blkif);
irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
int blkif_schedule(void *arg);
-void update_blkif_status(blkif_t *blkif);
-
#endif /* __BLKIF__BACKEND__COMMON_H__ */
/*
memset(blkif, 0, sizeof(*blkif));
blkif->domid = domid;
- blkif->status = DISCONNECTED;
spin_lock_init(&blkif->blk_ring_lock);
atomic_set(&blkif->refcnt, 1);
init_waitqueue_head(&blkif->wq);
blkif->irq = bind_evtchn_to_irqhandler(
blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif);
- /* We're potentially connected now */
- update_blkif_status(blkif);
-
return 0;
}
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-
#include <stdarg.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include "common.h"
#undef DPRINTK
-#define DPRINTK(fmt, args...) \
- pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
-
+#define DPRINTK(fmt, args...) \
+ pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", \
+ __FUNCTION__, __LINE__, ##args)
struct backend_info
{
struct xenbus_device *dev;
blkif_t *blkif;
struct xenbus_watch backend_watch;
-
unsigned major;
unsigned minor;
char *mode;
};
-
-static void maybe_connect(struct backend_info *);
static void connect(struct backend_info *);
static int connect_ring(struct backend_info *);
static void backend_changed(struct xenbus_watch *, const char **,
unsigned int);
-void update_blkif_status(blkif_t *blkif)
+static void update_blkif_status(blkif_t *blkif)
{
- if(blkif->irq && blkif->vbd.bdev) {
- blkif->status = CONNECTED;
- (void)blkif_be_int(0, blkif, NULL);
+ if (blkif->irq && blkif->vbd.bdev &&
+ (blkif->be->dev->state != XenbusStateConnected)) {
+ connect(blkif->be);
+ blkif_notify_work(blkif);
}
- maybe_connect(blkif->be);
}
be->backend_watch.node = NULL;
}
if (be->blkif) {
- be->blkif->status = DISCONNECTED;
if (be->blkif->xenblkd)
kthread_stop(be->blkif->xenblkd);
blkif_put(be->blkif);
return;
}
- if (be->major && be->minor &&
- (be->major != major || be->minor != minor)) {
+ if ((be->major || be->minor) &&
+ ((be->major != major) || (be->minor != minor))) {
printk(KERN_WARNING
"blkback: changing physical device (from %x:%x to "
"%x:%x) not supported.\n", be->major, be->minor,
/* ** Connection ** */
-static void maybe_connect(struct backend_info *be)
-{
- if ((be->major != 0 || be->minor != 0) &&
- be->blkif->status == CONNECTED)
- connect(be);
-}
-
-
/**
* Write the physical details regarding the block device to the store, and
* switch to Connected state.